<?php

/*
 * litchicms
 * Copyright (C) 2010-5-1 Author: tiefa(539247@qq.com)
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
!defined('BRK') && exit("!");

class category implements ArrayAccess, Iterator {

    public $id;
    public $lid;
    public $rid;
    public $name;
    public $type;
    public $note;
    public $sort;
    public $tpl;
    public $viewtpl;
    public $thumb;
    public $image;
    public $url;
    public $urlTarget;
    public $datanum;
    public $parent;
    public $numsub;
    public $sub;
    public $Has = FALSE;
    public $WHERE;

    function __construct($id=0, $type=NULL) {
        $this->category($id, $type);
    }

    function category($id=0, $type=NULL) {
        if ($type == NULL) {
            //出错提示
            exit('TYPE');
        }
        $this->id = $id;
        $this->lid = 0;
        $this->rid = 0;
        $this->name = "";
        $this->type = $type;
        $this->numsub = 0;
        $this->sub = array();
        $this->parent = NULL;
        $this->WHERE = " WHERE `ctype`='" . $type . "' AND ";
        if ($this->load()) {
            $this->Has = TRUE;
        }
    }

    //导入分类
    public function import(& $array) {
        $this->id = isset($array['cid']) ? $array['cid'] : $this->id;
        $this->lid = isset($array['lid']) ? $array['lid'] : $this->lid;
        $this->rid = isset($array['rid']) ? $array['rid'] : $this->rid;
        $this->name = isset($array['cname']) ? $array['cname'] : $this->name;
        $this->type = isset($array['ctype']) ? $array['ctype'] : $this->type;
        $this->note = isset($array['cnote']) ? $array['cnote'] : $this->note;
        $this->sort = isset($array['csort']) ? $array['csort'] : 0;
        $this->tpl = isset($array['ctpl']) ? $array['ctpl'] : $this->tpl;
        $this->viewtpl = isset($array['cviewtpl']) ? $array['cviewtpl'] : $this->viewtpl;
        $this->thumb = isset($array['cthumb']) ? $array['cthumb'] : $this->thumb;
        $this->image = isset($array['cimage']) ? $array['cimage'] : $this->image;
        $this->url = isset($array['curl']) ? $array['curl'] : $this->url;
        $this->urlTarget = isset($array['curlTarget']) ? $array['curlTarget'] : $this->urlTarget;
        $this->datanum = isset($array['cdatanum']) ? $array['cdatanum'] : $this->datanum;

        $this->numsub = ($this->rid - $this->lid - 1) / 2;
        //        dump($this->export());
    }

    //导出分类
    public function export($layer=0) {
        $result = array(
            'cid' => $this->id,
            'lid' => $this->lid,
            'rid' => $this->rid,
            'cname' => $this->name,
            'ctype' => $this->type,
            'cnote' => $this->note,
            'csort' => $this->sort,
            'ctpl' => $this->tpl,
            'cviewtpl' => $this->viewtpl,
            'cthumb' => $this->thumb,
            'cimage' => $this->image,
            'curl' => $this->url,
            'curlTarget' => $this->urlTarget,
            'cdatanum' => $this->datanum,
            'clayer' => $layer,
            'clayerstr' => str_repeat("─", $layer) . '<span style="color: red">|</span>'
        ); //
        return $result;
    }

    //加载分类
    public function load() {
        global $Db;
        if ($this->id == 0) {
            return FALSE;
        }
        $sql = "SELECT * FROM `!'category` " . $this->WHERE . " `cid`=" . $this->id;
        $rs = brk_query($sql); // $Db->query($sql);
        if ($Db->num_rows($rs) == 0) {
            //错误输出，没有此分类
            return FALSE;
        }
        $arrayTemp = $Db->fetch_array($rs);
        $this->import($arrayTemp);
        return TRUE;
    }

    //加载所有子集分类
    public function loadsub() {
        global $Db;
        if ($this->numsub == 0) {
            return FALSE;
        }
        $sql = "SELECT * FROM `!'category` " . $this->WHERE . " `lid`>" . $this->lid . " AND `rid`<" . $this->rid . " ORDER BY `lid` ASC";
        $rs = brk_query($sql); //$Db->query($sql);
        $num = $Db->num_rows($rs);
        $arrayTemp = array();
        for ($i = 0; $i < $num; $i++) {
            $arrayTemp[$i] = new category(0, $this->type);
            $arrayTemp[$i]->import($Db->fetch_array($rs));
        }
        cat2link($this, $arrayTemp);
        $Db->free_result($rs);
        return TRUE;
    }

    //设定左右值
    public function setLeft($delta) {
        $this->lid+=$delta;
        $this->rid = $this->numsub * 2 + $this->lid + 1;
        foreach ($this->sub as $k => $v) {
            $this->sub[$k]->setLeft($delta);
        }
    }

    //设置分类名
    public function setname($str) {
        if ($str == '' || count($str) > 255) {
            return false;
        }
        $this->name = $str;
        return TRUE;
    }

    //组装SQL语句中的字段
    //添加子分类
    public function add($cat, $save=FALSE) {
        if ($cat->name == '') {
            //出错  不能为空
            return FALSE;
        }
        if ($save) {
            $sql = "UPDATE `!'category` SET `rid`=`rid`+ " . (2 * ($cat->numsub + 1)) . " " . $this->WHERE . " `rid`>=" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $sql = "UPDATE `!'category` SET `lid`=`lid`+ " . (2 * ($cat->numsub + 1)) . " " . $this->WHERE . " `lid`>" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $this->rid += ( $cat->numsub + 1) * 2;
            $delta = ($this->rid - ($cat->numsub + 1) * 2 ) - $cat->lid;
            $cat->setLeft($delta);
            $this->rid+= ( $cat->numsub + 1) * 2;
            $this->sub[0] = & $cat;
            $this->sub[0]->parent = & $this;
            if ($save) {
                $arrayNew = cat2expert($cat, TRUE);
                $arrayQuery = array();

                //组装
                $fieldstr = formationField($arrayNew[0]);
                foreach ($arrayNew as $k => $v) {
                    $arrayQuery[$k] = formationValue($v);
                }
                $sql = "INSERT INTO `!'category`" . $fieldstr . " VALUES " . implode(",", $arrayQuery);
                brk_query($sql); //$Db->query($sql);
            }
            return TRUE;
        }
    }

    //删除该节点及其子节点
    public function destory($save=FALSE) {
        //if($this->id==1) {
        //不能删除根
        //    return FALSE;
        //}
        if (!$this->Has) {
            //不存在此分类
            echo ("不存在此分类");
            return FALSE;
        }
        if ($save) {
            $sql = "DELETE FROM `!'category` " . $this->WHERE . " `lid`>=" . $this->lid . " AND `rid`<=" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $sql = "UPDATE `!'category` SET `rid`=`rid`-" . (($this->numsub + 1) * 2) . " " . $this->WHERE . " `rid`>" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $sql = "UPDATE `!'category` SET `lid`=`lid`-" . (($this->numsub + 1) * 2) . " " . $this->WHERE . " `lid`>" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $this->setLeft(1 - $this->lid);
            return $this;
        }
    }

    //清空子分类
    public function clear($save=FALSE) {
        if ($this->numsub == 0) {
            //无子类
            return FALSE;
        }
        if ($save) {
            $sql = "DELETE FROM `!'category` " . $this->WHERE . " `lid`>" . $this->lid . " AND `rid`<" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $sql = "UPDATE `!'category` SET `rid`=`rid`-" . ($this->numsub * 2) . " " . $this->WHERE . " `rid`>=" . $this->rid;
            brk_query($sql); //$Db->query($sql);
            $sql = "UPDATE `!'category` SET `lid`=`lid`-" . ($this->numsub * 2) . " " . $this->WHERE . " `lid`>" . $this->rid;
            brk_query($sql); //$Db->query($sql);
        }
        $this->load();
        $this->loadsub();
        return TRUE;
    }

    //MOVE 不能将子类移动到自己的父级 不能将分类移动到自己的子类
    public function move($id, $type, $save=FALSE) {
        $id = intval($id);
        if ($save) {
            if (count($this->sub) == 0) {
                $this->loadsub();
            }

            $arrayTemp = cat2expert($this);

            $target = new category($id, $type);
            //目标是否是一个分类
            if ($target->name == "" || $target->id == $this->id) {
                return "不合法的移动";
            }

            $onum = ($this->numsub + 1) * 2;

            //上移
            if ($target->lid < $this->lid && $target->rid > $this->rid) {
                $sql = "UPDATE " . TPF . "category SET rid=rid-$onum " . $this->WHERE . "rid>" . $this->rid . " AND rid<" . $target->rid . " ";
                brk_query($sql); //$Db->query($sql);
                $sql = "UPDATE " . TPF . "category SET lid=lid-$onum " . $this->WHERE . "lid>" . $this->lid . " AND rid<" . $target->rid . " ";
                brk_query($sql); //$Db->query($sql);
                $this->setLeft($target->rid - $this->lid - $onum);
            }
            //左移
            elseif ($target->rid < $this->lid) {
                $sql = "UPDATE " . TPF . "category SET lid=lid+$onum " . $this->WHERE . "lid>" . $target->rid . " AND lid<" . $this->lid . " ";
                brk_query($sql); //$Db->query($sql);
                $sql = "UPDATE " . TPF . "category SET rid=rid+$onum " . $this->WHERE . "rid>=" . $target->rid . " AND rid<" . $this->lid . " ";
                brk_query($sql); //$Db->query($sql);
                $this->setLeft($target->rid - $this->lid);
            }
            //右移
            elseif ($target->lid > $this->rid) {
                $sql = "UPDATE " . TPF . "category SET lid=lid-$onum " . $this->WHERE . "lid>" . $this->rid . " AND lid<=" . $target->lid . " ";
                brk_query($sql); //$Db->query($sql);
                $sql = "UPDATE " . TPF . "category SET rid=rid-$onum " . $this->WHERE . "rid>" . $this->rid . " AND rid<" . $target->lid . " ";
                brk_query($sql); //$Db->query($sql);
                $this->setLeft($target->rid - $this->lid - $onum);
            } else {
                return "不合法的移动";
            }

            $arrayTemp = cat2expert($this);

            foreach ($arrayTemp as $value) {
                $dataarr = array(
                    'lid' => $value['lid'],
                    'rid' => $value['rid']
                );
                brk_update('category', $dataarr, "WHERE cid=" . $value['cid']);
            }
        }
        $this->load();
        $this->loadsub();
        return TRUE;
    }

    //copyto 复制到哪里
    public function copyto($id, $type, $save=FALSE) {
        if ($save) {
            if (count($this->sub) == 0) {
                $this->loadsub();
            }
            $buffer = $this;
            $target = new category($id, $type);
            if ($target->name == "" || $target->id == $this->id || ($target->lid < $this->lid && $target->rid > $this->rid)) {
                return FALSE;
            }
            $buffer->setLeft(1 - $this->lid);
            $target->add($buffer, $save);
        }
        $this->load();
        $this->loadsub();
        return TRUE;
    }

    //SAVE
    public function save() {
        if ($this->id == 0) {
            return FALSE;
        }
        $sql = "UPDATE `!'category` SET `lid`=" . $this->lid . " ,`rid`=" . $this->rid . " ,`cname`='" . $this->name . "' , `ctype`='" . $this->type . "' WHERE `cid`=" . $this->id;
        return brk_query($sql); //$Db->query($sql);
    }

    //GETPATH 获取当前类到根的路径
    public function getPath() {
        global $Db;
        $sql = "SELECT * FROM  `!'category` " . $this->WHERE . " `lid`<=" . $this->lid . " AND `rid`>=" . $this->rid . " ORDER BY `lid` ASC";
        $rs = brk_query($sql);
        $num = $Db->num_rows($rs);
        $arrayCat = array();
        $root = new category(0, $this->type);
        for ($i = 0; $i < $num; $i++) {
            $arrayTmp = $Db->fetch_array($rs);
            $tmpCat = new category(0, $this->type);
            $tmpCat->import($arrayTmp);
            $arrayCat[$tmpCat->id] = $tmpCat;
        }
        $Db->free_result($rs);
        return $arrayCat;
    }

    public function rewind() {
        reset($this->sub);
    }

    public function current() {
        $var = current($this->sub);
        return $var;
    }

    public function key() {
        $var = key($this->sub);
        return $var;
    }

    public function next() {
        $var = next($this->sub);
        return $var;
    }

    public function valid() {
        $var = $this->current() !== false;
        return $var;
    }

    public function offsetExists($offset) {
        return isset($this->$offset) ? TRUE : FALSE;
    }

    public function offsetGet($offset) {
        return isset($this->$offset) ? $this->$offset : null;
    }

    public function offsetSet($offset, $value) {
        $this->$offset = $value;
    }

    public function offsetUnset($offset) {
        unset($this->$offset);
    }

}

//归并左右值对象数组(左值起始)
function cat2link(& $parent, $array) {
    $result = array();
    $left = $parent->lid;
    $right = $parent->rid;
    if ($right - $left != 1) {
        foreach ($array as $key => $cat) {
            if ($left == $cat->lid - 1 && $cat->rid < $right) {
                $left = $cat->rid;
                //$cat->parent    = & $parent;
                $result[$cat->id] = $cat;
                cat2link($result[$cat->id], $array);
            }
        }
    }
    $parent->sub = $result;
}

//导出分类对象到二维数组
function cat2expert(& $cat) {
    $result = array();
    usort($cat->sub, 'cat_cmp');
    static $layer = 0;
    $layer++;
    foreach ($cat->sub as $sub) {
        if ($sub->numsub != 0) {
            $result = array_merge($result, cat2expert($sub));
        } else {
            array_push($result, $sub->export($layer));
        }
    }
    $layer--;
    $self = $cat->export($layer);
    array_unshift($result, $self);
    return $result;
}

function formationField($array) {
    unset($array['cid']);
    unset($array['clayer']);
    unset($array['clayerstr']);
    $fieldstr = "( ";
    foreach ($array as $ke => $va) {
        $fieldstr.=" `" . $ke . "` , ";
    }
    unset($getfieldarray);
    $fieldstr = substr($fieldstr, 0, -2);
    $fieldstr.=" )";
    return $fieldstr;
}

//组装SQL语句中的值
function formationValue($array) {
    unset($array['cid']);
    unset($array['clayer']);
    unset($array['clayerstr']);
    $strTemp = "( ";
    foreach ($array as $ke => $va) {
        $strTemp.=" '" . $va . "' , ";
    }
    $strTemp = substr($strTemp, 0, -2);
    $strTemp.=" )";
    return $strTemp;
}

//按照 csort 排序 倒序
function cat_cmp($a, $b) {
    if ($a['sort'] == $b['sort']) {
        //return 0;
    }
    return ($a['sort'] > $b['sort']) ? -1 : 1;
}

//$cate=new category(4,'news');
////$temp=($cate->getPath());
//$cate->loadsub();
//$quan=new category(0,'news');
//$quan->setname("速度书");
//$cate->add($quan, TRUE);
//$cate->move(61, "news",TRUE);

/*
  $cate->clear(TRUE);
  $quan=new category(0,'news');
  $quan->setname("文学");
  $cate->add($quan, TRUE);

  $cate->load();
  $quan=new category(0,'news');
  $quan->setname("历史小说");
  $cate->add($quan, TRUE);

  $destory=new category(45,'news');
  if($destory->destory(TRUE)) {
  echo "删除".$destory->id."OK";
  }
 */
?>